﻿using LMCWebStore.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using DefaulArchitecture.Message;

namespace LMCWebStore.Controllers
{
    #region BaseController

    public class BaseController : Controller
    {
        public UIMessage Messages { get; set; }
        public static string RenderPartialToString(string viewName, object model, ControllerContext ControllerContext, TempDataDictionary tempData = null)
        {
            if (string.IsNullOrWhiteSpace(viewName))
                viewName = ControllerContext.RouteData.GetRequiredString("action");

            ViewDataDictionary ViewData = new ViewDataDictionary();
            TempDataDictionary TempData = tempData != null ? tempData : new TempDataDictionary();

            if (model != null)
                ViewData.Model = model;

            using (StringWriter sw = new StringWriter())
            {
                try
                {
                    ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
                    ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
                    viewResult.View.Render(viewContext, sw);
                    return sw.GetStringBuilder().ToString();
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
            }
        }
    }

    #endregion

    #region ConfirmButton

    public enum ConfirmButton
    {
        Sim,
        Nao
    }

    #endregion

    #region JsonTreeView

    public class JsonTreeView : JsonResult
    {
        string propId;
        string propPai;
        string PropTexto;
        bool collapsed;

        public JsonTreeView(IEnumerable<object> Itens, string NomePropriedadePai, string NomePropriedadeId, string NomePropriedadeTexto, string IdTreeView, bool collapsed = true)
        {
            this.propId = NomePropriedadeId;
            this.propPai = NomePropriedadePai;
            this.PropTexto = NomePropriedadeTexto;

            this.collapsed = collapsed;

            string view = string.Empty;
            IEnumerable<object> Principais = Itens.Where(c => c.GetType().GetProperty(NomePropriedadePai).GetValue(c, null) == null);
            view = "<ul id=\"" + IdTreeView + "\" class=\"Tree\">";
            foreach (var item in Principais)
            {
                view += "<li class=\"TreeViewItem\" identificador=\"" + item.GetType().GetProperty(NomePropriedadeId).GetValue(item, null) + "\" >";
                view += "<span>" + item.GetType().GetProperty(NomePropriedadeTexto).GetValue(item, null) + "</span>";
                view = MontaArvore(view, Itens, item);
                view += "</li>";

            }
            view += "</ul>";

            this.Data = new { TreeView = view, TreeViewId = IdTreeView };
        }

        private string MontaArvore(string UlLi, IEnumerable<object> itens, object Pai)
        {
            IEnumerable<object> Itensfilhos;
            string display;
            List<object> filhos;
            int count;
            HasChild(itens, Pai, out Itensfilhos, out display, out filhos, out count);

            if (count > 0)
            {
                UlLi += string.Format("<ul {0}>", display);

                foreach (var item in filhos)
                {
                    dynamic cat = item;
                    if (Itensfilhos.Where(c => (int)c.GetType().GetProperty(propPai).GetValue(c, null).GetType().GetProperty(propId).GetValue(c, null) == cat.Id).Count() > 0)
                    {
                        HasChild(itens, item, out Itensfilhos, out display, out filhos, out count);
                        object objPai = item.GetType().GetProperty(propPai).GetValue(item, null);
                        int idPai = (int)objPai.GetType().GetProperty(propId).GetValue(objPai, null);

                        if (count == 0)
                            UlLi += "<li CountChildren=\"0\" IdentificadorPai=\" " + idPai + "\" class=\"TreeViewItem\" identificador=\"" + item.GetType().GetProperty(propId).GetValue(item, null) + "\" >";
                        else
                            UlLi += "<li CountChildren=\"1\"  IdentificadorPai=\" " + idPai + "\" class=\"TreeViewItem\" identificador=\"" + item.GetType().GetProperty(propId).GetValue(item, null) + "\" >";

                        UlLi += "<span >" + item.GetType().GetProperty(PropTexto).GetValue(item, null) + "</span>";
                        UlLi = MontaArvore(UlLi, itens, item);
                        UlLi += "</li>";
                    }
                    else
                    {
                        UlLi += "<li class=\"TreeViewItem\" identificador=\"" + item.GetType().GetProperty(propId).GetValue(item, null) + "\" >";
                        UlLi += "<span>" + item.GetType().GetProperty(PropTexto).GetValue(item, null) + "</span>";
                        UlLi += "</li>";
                    }
                }

                UlLi += "</ul>";
            }

            return UlLi;
        }

        private void HasChild(IEnumerable<object> itens, object Pai, out IEnumerable<object> Itensfilhos, out string display, out List<object> filhos, out int count)
        {
            Itensfilhos = itens.Where(c => c.GetType().GetProperty(propPai).GetValue(c, null) != null);

            display = "style=\"display:" + (this.collapsed ? "none\"" : "block\"") + ";";
            var idPai = 0;
            idPai = (int)Pai.GetType().GetProperty(propId).GetValue(Pai, null);
            filhos = new List<object>();

            foreach (var ItemFilho in Itensfilhos)
            {
                dynamic itemPai = ItemFilho.GetType().GetProperty(propPai).GetValue(ItemFilho, null);
                if (itemPai.Id == idPai)
                {
                    filhos.Add(ItemFilho);
                }
            }

            count = filhos.Count();
        }
    }

    #endregion

    #region JsonError

    public class JsonError : JsonResult
    {
        // Adicionar 2 parâmetros no AjaxMVC para anular o onSucesso geral e o onErro geral, para dar mais flexibilidade na hora de mostrar mensagens
        public JsonError(string NomePartialView, object Model, string SeletorContainerRetorno, ControllerContext controllerContext, object ExtraData = null)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new
            {
                ResultType = "JsonError",
                Type = "ERROR",
                ExtraData = ExtraData,
                ContainerMessage = SeletorContainerRetorno,
                AppendRetorno = false,
                ViewMessage = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext)
            };
        }
    }

    #endregion

    #region JsonSuccess

    public class JsonSuccess : JsonResult
    {
        public JsonSuccess(string NomePartialView, object Model, string SeletorContainerRetorno, ControllerContext controllerContext, object ExtraData = null)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new
            {
                ResultType = "JsonSuccess",
                Type = "SUCCESS",
                ExtraData = ExtraData,
                ContainerMessage = SeletorContainerRetorno,
                AppendRetorno = false,
                ViewMessage = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext)
            };
        }
    }

    #endregion

    #region JsonConfirmWithRedirect

    public class JsonConfirmWithRedirect : JsonResult
    {
        public JsonConfirmWithRedirect(TipoMensagem tipoMensagem, object Model, string NomePartialView, string Controller, string Action, ControllerContext controllerContext, string TituloConfirm = "", ConfirmButton BotaoRedirecionamento = ConfirmButton.Nao)
        {
            if (string.IsNullOrWhiteSpace(TituloConfirm) && tipoMensagem == TipoMensagem.Erro)
            {
                TituloConfirm = "Erro";
            }
            if (string.IsNullOrWhiteSpace(TituloConfirm) && tipoMensagem == TipoMensagem.Sucesso)
            {
                TituloConfirm = "Sucesso";
            }

            this.Data = new { UseAlert = false, Sucesso = true, Titulo = TituloConfirm, ConfirmaButton = BotaoRedirecionamento, Tipo = (int)tipoMensagem, Controller = Controller, Action = Action, ViewMensagem = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext) };
        }

        public JsonConfirmWithRedirect(TipoMensagem tipoMensagem, object Model, string NomePartialView, string Controller, string Action, object RouteValues, ControllerContext controllerContext, string TituloConfirm = "", ConfirmButton BotaoRedirecionamento = ConfirmButton.Nao)
        {
            string queryString = string.Empty;

            if (string.IsNullOrWhiteSpace(TituloConfirm) && tipoMensagem == TipoMensagem.Erro)
            {
                TituloConfirm = "Erro";
            }
            if (string.IsNullOrWhiteSpace(TituloConfirm) && tipoMensagem == TipoMensagem.Sucesso)
            {
                TituloConfirm = "Sucesso";
            }

            foreach (PropertyInfo item in RouteValues.GetType().GetProperties())
            {
                if (string.IsNullOrWhiteSpace(queryString))
                    queryString = string.Format("?{0}={1}", item.Name, item.GetValue(RouteValues, null).ToString());
                else
                    queryString += string.Format("&{0}={1}", item.Name, item.GetValue(RouteValues, null).ToString());
            }

            Action += queryString;

            this.Data = new { UseAlert = false, Titulo = TituloConfirm, ConfirmaButton = BotaoRedirecionamento, Controller = Controller, Action = Action, Tipo = (int)tipoMensagem, ViewMensagem = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext) };
        }
    }

    #endregion

    #region JsonRedirect

    public class JsonRedirect : JsonResult
    {
        public JsonRedirect(string Controller, string Action, ControllerContext controllerContext)
        {
            string scheme = String.Format("{0}://", controllerContext.HttpContext.Request.Url.Scheme);
            string u = controllerContext.HttpContext.Request.Url.Authority;
            string url = String.Format("{0}/{1}/{2}/{3}", scheme, u, Controller, Action);
            this.Data = new { RedirectUrl = url };
        }

        public JsonRedirect(string Controller, string Action, object RouteValues, ControllerContext controllerContext)
        {
            string queryString = string.Empty;
            string scheme = String.Format("{0}://", controllerContext.HttpContext.Request.Url.Scheme);
            string u = controllerContext.HttpContext.Request.Url.Authority;
            string url = String.Format("{0}/{1}/{2}/{3}", scheme, u, Controller, Action);

            foreach (PropertyInfo item in RouteValues.GetType().GetProperties())
            {
                if (string.IsNullOrWhiteSpace(queryString))
                    queryString = string.Format("?{0}={1}", item.Name, item.GetValue(RouteValues, null).ToString());
                else
                    queryString += string.Format("&{0}={1}", item.Name, item.GetValue(RouteValues, null).ToString());
            }

            url += queryString;

            this.Data = new { RedirectUrl = url };
        }
    }

    #endregion

    #region JsonModal

    public class JsonModal : JsonResult
    {
        public JsonModal(string NomePartialView, object Model, ControllerContext controllerContext)
        {

            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new
            {
                IdModal = DateTime.Now.Ticks,
                ResultType = "JsonModal",
                View = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext)
            };
        }

        public JsonModal(string NomePartialView, string TituloModal, object Model, ControllerContext controllerContext)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new
            {
                IdModal = DateTime.Now.Ticks,
                ResultType = "JsonModal",
                Titulo = TituloModal,
                View = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext)
            };
        }

        public JsonModal(string NomePartialView, string TituloModal, object Model, ControllerContext controllerContext, TempDataDictionary TempData)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new
            {
                IdModal = DateTime.Now.Ticks,
                Titulo = TituloModal,
                ResultType = "JsonModal",
                View = BaseController.RenderPartialToString(NomePartialView, Model, controllerContext, TempData)
            };
        }
    }

    #endregion

    #region JsonPartial

    public class JsonPartial : JsonResult
    {
        public JsonPartial(object ModelRetorno, string ViewRetorno, string SeletorContainerRetorno, bool AppendContent, ControllerContext controllerContext, object ExtraData = null)
            : this(BaseController.RenderPartialToString(ViewRetorno, ModelRetorno, controllerContext), SeletorContainerRetorno, AppendContent, ExtraData)
        {
        }

        public JsonPartial(string Partial, string SeletorContainerRetorno, bool AppendContent, object ExtraData = null)
        {
            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new
            {
                ResultType = "JsonPartial",
                ExtraData = ExtraData,
                ContainerContent = SeletorContainerRetorno,
                AppendRetorno = AppendContent,
                ViewContent = Partial
            };
        }
    }

    #endregion

    #region JsonMesageWithPartial

    public class JsonMesageWithPartial : JsonResult
    {
        public JsonMesageWithPartial(Boolean SuccessMessage, object ModelMensagem, string ViewMensagem, object ModelRetorno, string ViewRetorno, string ContainerMessageSelector, string ContainerContentSelector, bool AppendContent, ControllerContext controllerContext, object ExtraData = null)
        {

            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new
            {
                ResultType = "JsonMesageWithPartial",
                ExtraData = ExtraData,
                Type = SuccessMessage ? "SUCCESS" : "ERROR",
                ViewMessage = BaseController.RenderPartialToString(ViewMensagem, ModelMensagem, controllerContext),
                ViewContent = BaseController.RenderPartialToString(ViewRetorno, ModelRetorno, controllerContext),
                ContainerMessage = ContainerMessageSelector,
                ContainerContent = ContainerContentSelector,
                AppendContent = AppendContent,
            };
        }

        public JsonMesageWithPartial(Boolean SuccessMessage, object ModelMensagem, string ViewMensagem, string HtmlContent, string ContainerMessageSelector, string ContainerContentSelector, bool AppendContent, ControllerContext controllerContext, object ExtraData = null)
        {

            this.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
            this.Data = new
            {
                ResultType = "JsonMesageWithPartial",
                ExtraData = ExtraData,
                Type = SuccessMessage ? "SUCCESS" : "ERROR",
                ViewMessage = BaseController.RenderPartialToString(ViewMensagem, ModelMensagem, controllerContext),
                ViewContent = HtmlContent,
                ContainerMessage = ContainerMessageSelector,
                ContainerContent = ContainerContentSelector,
                AppendContent = AppendContent,
            };
        }
    }

    #endregion
}